﻿namespace Baddies.InputDevices
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics; 
    using System.Linq;
    using System.Text;
    using Baddies.Events;
    using Baddies.GUI;    
    using Baddies.Nodes;
    using Microsoft.Xna.Framework.Input;    
       
    /// <summary>
    /// Interprets the physical input of the player and sends
    /// messages that the mode interprets as he will.
    /// Always on top of all the other nodes.
    /// </summary>
    public class InputDevice : Node
    {
        /// <summary>
        /// Current mouse state.
        /// </summary>
        private MouseState curMouseState;

        /// <summary>
        /// Previous mouse state.
        /// </summary>
        private MouseState preMouseState;
        
        /// <summary>
        /// Current keyboard state.
        /// </summary>
        private KeyboardState curKeyboardState;

        /// <summary>
        /// Previous keyboard state.
        /// </summary>
        private KeyboardState preKeyboardState;

        /// <summary>
        /// Reference to the current focused node.
        /// </summary>
        private GUINode focusedNode;

        /// <summary>
        /// Gets or sets the focused node.
        /// </summary>
        /// <value>Reference to the focused node.</value>
        public GUINode FocusedNode
        {
            get 
            {
                return this.focusedNode;
            }

            set
            {                
                Debug.Assert(this.Contains(value), "The node provided is not a child of the InputDevice!");
                this.focusedNode = value;
            }
        }

        /// <summary>
        /// Initializes a new instance of the InputDevice class.
        /// </summary>
        public InputDevice()
            : base()
        {
            this.DirectSetZ(-1);

            this.preKeyboardState = Keyboard.GetState();
            this.curKeyboardState = Keyboard.GetState();
            this.curMouseState = Mouse.GetState();
            this.preMouseState = Mouse.GetState();

            this.focusedNode = null;

            EventManager.GetEV.RegisterNewEvent("KeyPress", true);
        }

        /// <summary>
        /// Updates the InputDevice.
        /// </summary>
        public override void Update()
        {
            base.Update();

            this.curKeyboardState = Keyboard.GetState();
            this.curMouseState = Mouse.GetState();
            bool focusWant = false;

            // Get mouse input
                // See if the focused GUINode wants it
                // If so, feed it to it.
                // Else se if ithe click focuses something else, and unfocus current
                // Else, unfocus current and message the rest of the system
            
            // Get keyboard input
            foreach (Keys key in this.curKeyboardState.GetPressedKeys())
            {
                focusWant = false;
                if (this.preKeyboardState.IsKeyUp(key))
                {                    
                    if (this.focusedNode != null)
                    {
                        // See if the focused GUINode wants it
                        focusWant = this.focusedNode.React(key);
                    }

                    if (!focusWant)
                    {
                        // If not, send to system, see if anyone wants it.
                        KeyPressArg args = new KeyPressArg();
                        args.Key = key;
                        EventManager.GetEV.Trigger("KeyPress", this, args);
                    }
                }
            }

            this.preMouseState = this.curMouseState;
            this.preKeyboardState = this.curKeyboardState;
        }
    }
}
